export const list = [{
	question: 'JavaScript有哪些数据类型，它们的区别？',
	answer: `JavaScript共有八种数据类型，分别是 Undefined、Null、Boolean、Number、String、Object、Symbol、BigInt。
	其中 Symbol 和 BigInt 是ES6 中新增的数据类型：

	Symbol 代表创建后独一无二且不可变的数据类型， 它主要是为了解决可能出现的全局变量冲突的问题。
	BigInt 是一种数字类型的数据， 它可以表示任意精度格式的整数， 使用 BigInt 可以安全地存储和操作大整数， 即使这个数已经超出了 Number 能够表示的安全整数范围。

	这些数据可以分为原始数据类型和引用数据类型：

	栈： 原始数据类型（ Undefined、 Null、 Boolean、 Number、 String）
	堆： 引用数据类型（ 对象、 数组和函数）

	两种类型的区别在于存储位置的不同：

	原始数据类型直接存储在栈（ stack） 中的简单数据段， 占据空间小、 大小固定， 属于被频繁使用数据， 所以放入栈中存储；
	引用数据类型存储在堆（ heap） 中的对象， 占据空间大、 大小不固定。 如果存储在栈中， 将会影响程序运行的性能； 引用数据类型在栈中存储了指针， 该指针指向堆中该实体的起始地址。 当解释器寻找引用值时， 会首先检索其在栈中的地址， 取得地址后从堆中获得实体。

	堆和栈的概念存在于数据结构和操作系统内存中， 在数据结构中：

	在数据结构中， 栈中数据的存取方式为先进后出。
	堆是一个优先队列， 是按优先级来进行排序的， 优先级可以按照大小来规定。

	在操作系统中， 内存被分为栈区和堆区：

	栈区内存由编译器自动分配释放， 存放函数的参数值， 局部变量的值等。 其操作方式类似于数据结构中的栈。
	堆区内存一般由开发着分配释放， 若开发者不释放， 程序结束时可能由垃圾回收机制回收。`
}, {
	question: '数据类型检测的方式有哪些',
	answer: `（1）typeof
console.log(typeof 2);               // number
console.log(typeof true);            // boolean
console.log(typeof 'str');           // string
console.log(typeof []);              // object    
console.log(typeof function(){});    // function
console.log(typeof {});              // object
console.log(typeof undefined);       // undefined
console.log(typeof null);            // object
复制代码
其中数组、对象、null都会被判断为object，其他判断都正确。
（2）instanceof
instanceof可以正确判断对象的类型，其内部运行机制是判断在其原型链中能否找到该类型的原型。
console.log(2 instanceof Number);                    // false
console.log(true instanceof Boolean);                // false 
console.log('str' instanceof String);                // false 
 
console.log([] instanceof Array);                    // true
console.log(function(){} instanceof Function);       // true
console.log({} instanceof Object);                   // true
复制代码
可以看到，instanceof只能正确判断引用数据类型，而不能判断基本数据类型。instanceof 运算符可以用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。
（3） constructor
console.log((2).constructor === Number); // true
console.log((true).constructor === Boolean); // true
console.log(('str').constructor === String); // true
console.log(([]).constructor === Array); // true
console.log((function() {}).constructor === Function); // true
console.log(({}).constructor === Object); // true
复制代码
constructor有两个作用，一是判断数据的类型，二是对象实例通过 constrcutor 对象访问它的构造函数。需要注意，如果创建一个对象来改变它的原型，constructor就不能用来判断数据类型了：
function Fn(){};
 
Fn.prototype = new Array();
 
var f = new Fn();
 
console.log(f.constructor===Fn);    // false
console.log(f.constructor===Array); // true
复制代码
（4）Object.prototype.toString.call()
Object.prototype.toString.call() 使用 Object 对象的原型方法 toString 来判断数据类型：
var a = Object.prototype.toString;
 
console.log(a.call(2));
console.log(a.call(true));
console.log(a.call('str'));
console.log(a.call([]));
console.log(a.call(function(){}));
console.log(a.call({}));
console.log(a.call(undefined));
console.log(a.call(null));
复制代码
同样是检测对象obj调用toString方法，obj.toString()的结果和Object.prototype.toString.call(obj)的结果不一样，这是为什么？
这是因为toString是Object的原型方法，而Array、function等类型作为Object的实例，都重写了toString方法。不同的对象类型调用toString方法时，根据原型链的知识，调用的是对应的重写之后的toString方法（function类型返回内容为函数体的字符串，Array类型返回元素组成的字符串…），而不会去调用Object上原型toString方法（返回对象的具体类型），所以采用obj.toString()不能得到其对象类型，只能将obj转换为字符串类型；因此，在想要得到对象的具体类型时，应该调用Object原型上的toString方法。
`
},{"question": "null和undefined区别", "answer": `首先 Undefined 和 Null 都是基本数据类型，这两个基本数据类型分别都只有一个值，就是 undefined 和 null。
undefined 代表的含义是未定义，null 代表的含义是空对象。一般变量声明了但还没有定义的时候会返回 undefined，null主要用于赋值给一些可能会返回对象的变量，作为初始化。
undefined 在 JavaScript 中不是一个保留字，这意味着可以使用 undefined 来作为一个变量名，但是这样的做法是非常危险的，它会影响对 undefined 值的判断。我们可以通过一些方法获得安全的 undefined 值，比如说 void 0。
当对这两种类型使用 typeof 进行判断时，Null 类型化会返回 “object”，这是一个历史遗留的问题。当使用双等号对两种类型的值进行比较时会返回 true，使用三个等号时会返回 false`},{"question": `为什么0.1+0.2 ! == 0.3，如何让其相等`, "answer": `toFixed(num) 方法可把 Number 四舍五入为指定小数位数的数字。那为什么会出现这样的结果呢？
计算机是通过二进制的方式存储数据的，所以计算机计算0.1+0.2的时候，实际上是计算的两个数的二进制的和。0.1的二进制是0.0001100110011001100...（1100循环），0.2的二进制是：0.00110011001100...（1100循环），这两个数的二进制都是无限循环的数。那JavaScript是如何处理无限循环的二进制小数呢？
一般我们认为数字包括整数和小数，但是在 JavaScript 中只有一种数字类型：Number，它的实现遵循IEEE 754标准，使用64位固定长度来表示，也就是标准的double双精度浮点数。在二进制科学表示法中，双精度浮点数的小数部分最多只能保留52位，再加上前面的1，其实就是保留53位有效数字，剩余的需要舍去，遵从“0舍1入”的原则。
根据这个原则，0.1和0.2的二进制数相加，再转化为十进制数就是：0.30000000000000004`},{"question": `let、const、var的区别`, "answer": `（1）块级作用域： 块作用域由 { }包括，let和const具有块级作用域，var不存在块级作用域。块级作用域解决了ES5中的两个问题：

内层变量可能覆盖外层变量
用来计数的循环变量泄露为全局变量

（2）变量提升： var存在变量提升，let和const不存在变量提升，即在变量只能在声明之后使用，否在会报错。
（3）给全局添加属性： 浏览器的全局对象是window，Node的全局对象是global。var声明的变量为全局变量，并且会将该变量添加为全局对象的属性，但是let和const不会。
（4）重复声明： var声明变量时，可以重复声明变量，后声明的同名变量会覆盖之前声明的遍历。const和let不允许重复声明变量。
（5）暂时性死区： 在使用let、const命令声明变量之前，该变量都是不可用的。这在语法上，称为暂时性死区。使用var声明的变量不存在暂时性死区。
（6）初始值设置： 在变量声明时，var 和 let 可以不用设置初始值。而const声明变量必须设置初始值。
（7）指针指向： let和const都是ES6新增的用于创建变量的语法。 let创建的变量是可以更改指针指向（可以重新赋值）。但const声明的变量是不允许改变指针的指向。
`}]
